#ifndef mem_space_h
#define mem_space_h

// all dependencies
#include "basic_types.h"
#include <stdlib.h>

// first complex data type, mem_space,
// a byte array with a length
typedef struct
{
  owl_byte * ptr;
  owl_umax size;
} owl_mem_space;

// error codes for the memory allocator
typedef enum
{
  OWL_MEM_SPACE_NO_ERR,       // nothing has happened
  OWL_MEM_SPACE_TB_FULL,      // the table is full
  OWL_MEM_SPACE_CALLOC_FAIL,  // a call to calloc() failed
} owl_mem_space_err;

typedef enum
{
  OWL_TYPE_MEM_SPACE = OWL_TYPE_BOOL + 1,
  OWL_TYPE_MEM_SPACE_ERR,
} owl_type_mem_space_h;

// size of the pointer table
#define OWL_MEM_SPACE_TB_SIZE 50
owl_umax OWL_MEM_SPACE_TB_FREE_SLOTS = OWL_MEM_SPACE_TB_SIZE;
// global alloc error
owl_mem_space_err OWL_MEM_SPACE_GLOB_ERR = OWL_MEM_SPACE_NO_ERR;

// memory space table
// table defined to keep track of all variables based on mem_space
// (everything that will come after this header basically)
// All memory allocated pointers will be stored in this table.
// All pointers in this table will be NULL at first.
// This table helps (at least helps me) to avoid memory leaks
// and to avoid making so much memory allocations at once.
// also the name it has sounds very interesting and advanced
owl_mem_space OWL_MEM_SPACE_TB[OWL_MEM_SPACE_TB_SIZE] = {{NULL, 0}};

// basic functions
owl_bool owl_check_mem_space_pointer(owl_byte * src, owl_umax size);
owl_bool owl_check_mem_space_members(owl_byte * ptr, owl_umax size);
owl_bool owl_check_mem_space_all(owl_mem_space * src, owl_umax size);
owl_mem_space * owl_create_mem_space(owl_umax size);
owl_umax owl_free_mem_space(owl_mem_space * space);
owl_umax owl_print_mem_space(owl_byte * src, owl_umax size);
owl_char owl_comp_mem_space(owl_byte * mem_space1, owl_byte * mem_space2);

// other functions
void owl_print_mem_space_tb_err(void);

#include "mem_space.c"

#endif // mem_space_h
